﻿#include "customfileparser.h"
#include "gdal_priv.h"
#include "Public/appsignal.h"
#include "xlsxdocument.h"
#include "ExcelFormat.h"
#include "Log/logger.h"

#include <thread>
#include <fstream>
#include <regex>

#include <QDateTime>
#include <QFileInfo>

// test
#include <QDebug>

using namespace std;
using namespace ExcelFormat;

CustomFileParser::CustomFileParser(QObject *parent)
    : QObject{parent}
{
    GDALAllRegister();
}

void CustomFileParser::parse(const QString &path)
{
    std::lock_guard<std::mutex> lock(mMutex);
    if (mParseFlag)
    {
        // 发送系统消息
        return;
    }

    auto func = std::bind(&CustomFileParser::threadParse, this, path);
    std::thread th(func);
    th.detach();
}

void CustomFileParser::exportPointData(const QString& fileName, const QList<PointDetail>& detail)
{
    auto func = std::bind(&CustomFileParser::threadExportPointData, this, fileName, detail);
    std::thread th(func);
    th.detach();
}

void CustomFileParser::threadParse(const QString &path)
{
    bool parseStart = false;
    QFileInfo fileInfo(path);
    if (fileInfo.suffix().contains("tif", Qt::CaseInsensitive))
    {
        parseStart = true;
        parseGeotiff(path);
    }
    else if (fileInfo.suffix() == "xlsx")
    {
        QXlsx::Document xlsxDocument(path);
        if (!xlsxDocument.isLoadPackage())
        {
            emit AppSignal::getInstance()->sgl_occur_system_error("文件打开失败");
            // 发送系统消息
            std::lock_guard<std::mutex> lock(mMutex);
            mParseFlag = false;
            return;
        }

        auto listSheetName = xlsxDocument.sheetNames();
        // 查看第一张表是否存在，不存在报告没有找到数据
        if (listSheetName.size() == 0)
        {
            emit AppSignal::getInstance()->sgl_occur_system_error("表格文件为空");
            return;
        }
        // 默认使用第一张表 （表序号从 0 开始）
        xlsxDocument.selectSheet(0);

        QXlsx::CellRange range = xlsxDocument.dimension();
        if ((range.rowCount() <= 0) || (range.columnCount() <= 0))
        {
            emit AppSignal::getInstance()->sgl_occur_system_error("表格文件为空");
            return;
        }

        QXlsx::Cell cell = xlsxDocument.cellAt(1, 1);
        if (cell.value().toString().contains("NavigationLog"))
        {
            parseStart = true;
            parseVersion6(path);
        }
    }
    else if (fileInfo.suffix() == "xls")
    {
        BasicExcel xls(path.toStdString().data());
        if (xls.GetTotalWorkSheets() == 0)
        {
            emit AppSignal::getInstance()->sgl_occur_system_error("文件打开失败");
            // 发送系统消息
            std::lock_guard<std::mutex> lock(mMutex);
            mParseFlag = false;
            xls.Close();
            return;
        }

        BasicExcelWorksheet* sheet = xls.GetWorksheet(0);
        int rows = sheet->GetTotalRows();
        int cols = sheet->GetTotalCols();
        if (rows < 1 || cols < 5)
        {
            emit AppSignal::getInstance()->sgl_occur_system_error("表格文件格式无法解析");
            return;
        }

        QString header = sheet->Cell(0, 0)->GetString();
        xls.Close();
        if (header.contains("NavigationLog"))
        {
            parseStart = true;
            parseVersion7(path);
        }
    }
    else
    {
        ifstream fileDescripter(path.toLocal8Bit());
        if (!fileDescripter.is_open())
        {
            emit AppSignal::getInstance()->sgl_occur_system_error("文件打开失败");
            // 发送系统消息
            std::lock_guard<std::mutex> lock(mMutex);
            mParseFlag = false;
            return;
        }

        QString error;
        string line;
        while (getline(fileDescripter, line))
        {
            QString value = QString::fromStdString(line).trimmed();
            if (value.isEmpty()) continue;

            if (value.contains("UTM zone"))
            {
                regex pattern("^(.*)UTM zone:(.*),(.*)$");
                string text = value.toStdString();
                smatch results;
                if (std::regex_match(text, results, pattern))
                {
                    if (results.size() == 4)
                    {
                        int utmZone = stoi(results[2].str());
                        parseVersion1(utmZone, fileDescripter);
                        parseStart = true;
                    }
                }

                error = "file head error";
            }
            else if (value.startsWith("\"$GPRMC"))
            {
                // 重定位读取位置
                fileDescripter.seekg((line.length() + 2) * -1, ios::cur);
                parseVersion2(fileDescripter);
                parseStart = true;
                break;
            }
            else if (value.startsWith("\"$GPGGA"))
            {
                // 重定位读取位置
                fileDescripter.seekg((line.length() + 2) * -1, ios::cur);
                parseVersion3(fileDescripter);
                parseStart = true;
                break;
            }
            else if (value.startsWith("$PTSAG"))
            {
                // 重定位读取位置
                fileDescripter.seekg((line.length() + 2) * -1, ios::cur);
                parseVersion4(fileDescripter);
                parseStart = true;
                break;
            }
            else if (value.contains("System:"))
            {
                parseVersion5(fileDescripter);
                parseStart = true;
                break;
            }
            else if (isDefaultVersion(value))
            {
                // 重定位读取位置
                fileDescripter.seekg((line.length() + 2) * -1, ios::cur);
                parseVersion0(fileDescripter);
                parseStart = true;
                break;
            }
            else
            {
                LOG_DEBUG("unsupport format, next ");
            }
        }
    }

    if (!parseStart)
    {
        emit AppSignal::getInstance()->sgl_occur_system_error(QString("没有找到匹配的格式： %1").arg(fileInfo.fileName()));
    }
}

void CustomFileParser::parseGeotiff(const QString &path)
{
    // 此处计算图片的经纬度范围，防止查询的时候再计算耗时
    GDALDataset *poDataset;
    poDataset = (GDALDataset *)GDALOpen(path.toStdString().data(), GA_ReadOnly);
    if(poDataset == nullptr)
    {
       // can not open
       emit AppSignal::getInstance()->sgl_occur_system_error(QString("图片 %1 加载失败").arg(path));
       return;
    }
    int xLength = 0, yLength = 0;
    xLength = poDataset->GetRasterXSize();
    yLength = poDataset->GetRasterYSize();

    double adfGeoTransform[6];
    if(poDataset->GetGeoTransform(adfGeoTransform) != CE_None )
    {
       // can not open
       emit AppSignal::getInstance()->sgl_occur_system_error("读取经纬度信息失败");
       GDALClose((GDALDatasetH)poDataset);
       return;
    }

    double topLeftLongitude = adfGeoTransform[0];
    double bottomRightLongitude = adfGeoTransform[0] + xLength * adfGeoTransform[1] + yLength * adfGeoTransform[2];
    double topLeftLatitude = adfGeoTransform[3] + xLength * adfGeoTransform[4] + yLength * adfGeoTransform[5];
    double bottomRightLatitude = adfGeoTransform[3];

    // 此处可能需要进行一次转换，因为存在 墨卡托坐标系 的坐标

    // 投影坐标
    OGRSpatialReference spatialReference;
    OGRErr error = spatialReference.importFromWkt(poDataset->GetProjectionRef());
    if (OGRERR_NONE == error)
    {
       spatialReference.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
       // 地理坐标
       OGRSpatialReference *pLonLat = spatialReference.CloneGeogCS();
       OGRCoordinateTransformation *mLonLat2XY = OGRCreateCoordinateTransformation(&spatialReference, pLonLat);

       if (!mLonLat2XY->Transform(1, &topLeftLongitude, &topLeftLatitude) || !mLonLat2XY->Transform(1, &bottomRightLongitude, &bottomRightLatitude))
       {
           // can not translate
           emit AppSignal::getInstance()->sgl_occur_system_error("经纬度信息转换失败");
           GDALClose((GDALDatasetH)poDataset);
           return;
       }
    }

    QPointF p1 = QPointF(topLeftLongitude, bottomRightLatitude);
    QPointF p2 = QPointF(bottomRightLongitude, topLeftLatitude);

    QImage image(path); image.convertTo(QImage::Format_RGBA8888);
    if (image.isNull())
    {
        emit AppSignal::getInstance()->sgl_occur_system_error("图片加载失败");
        return;
    }

    TiffDetail result = {true, (float)p1.x(), (float)p1.y(), (float)p2.x(), (float)p2.y(), image};
    emit AppSignal::getInstance()->sgl_parse_tiff_result(result);
}

void CustomFileParser::parseVersion0(ifstream &fileDescripter)
{
    QList<PointDetail> listData;
    string line;
    while (getline(fileDescripter, line))
    {
        QString value = QString::fromStdString(line).trimmed().remove('\n');
        QStringList list = value.split(' ', Qt::SkipEmptyParts);

        if (list.length() != 3) continue;

        QDateTime datetime = QDateTime::fromString(list.at(2), "yyyy-MM-dd-hh:mm:ss.zzz");

        // 时间戳
        uint32_t timeStamp = datetime.toSecsSinceEpoch();
        QString dateTimeString = datetime.toString("yyyy-MM-dd hh:mm:ss");

        // 经度
        QString lon = list.at(0);
        double longitude = lon.toDouble();

        // 纬度
        QString lat = list.at(1);
        double latitude = lat.toDouble();

        listData.append({ dateTimeString.toStdString(), timeStamp, longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);

    fileDescripter.close();
}

void CustomFileParser::parseVersion1(int utmZone, ifstream &fileDescripter)
{
    // 最后一行 X 坐标
    double lastLongitude = -1;

    // 投影坐标
    OGRSpatialReference spatialReference;
    spatialReference.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
    spatialReference.SetUTM(utmZone, true);

    // 地理坐标
    OGRSpatialReference *pLonLat = spatialReference.CloneGeogCS();
    OGRCoordinateTransformation *mLonLat2XY = OGRCreateCoordinateTransformation(&spatialReference, pLonLat);
    if (nullptr == mLonLat2XY)
    {
        LOG_DEBUG("坐标转换依赖库异常，请联系管理员");
        return;
    }

    QList<PointDetail> listData;
    string line;
    while (getline(fileDescripter, line))
    {
        QString value = QString::fromStdString(line).trimmed().remove('\n');

        regex pattern("^[0-9\\.\\-\\,\\:]*$");
        smatch results;
        string text = value.toStdString();
        if (!regex_match(text, results, pattern))
        {
            LOG_DEBUG("数据异常，无法解析，跳过");
            continue;
        }

        QStringList list = value.split(',', Qt::SkipEmptyParts);
        if (list.size() != 12) continue;

        QString dateTimeString = QString("%1-%2").arg(list.at(0), list.at(1));
        QDateTime datetime = QDateTime::fromString(dateTimeString, "yyyy-MM-dd-hh:mm:ss.zzz");
        if (!datetime.isValid()) continue;

        double longitude = list.at(3).toDouble();

        double range = longitude - lastLongitude;
        if ((lastLongitude > 0) && (range < (100000 * -1))) // 加区
        {
            utmZone += 1;
            // 投影坐标
            OGRSpatialReference spatialReference;
            spatialReference.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
            spatialReference.SetUTM(utmZone, true);

            // 地理坐标
            OGRSpatialReference *pLonLat = spatialReference.CloneGeogCS();
            mLonLat2XY = OGRCreateCoordinateTransformation(&spatialReference, pLonLat);
        }
        else if ((lastLongitude > 0) && (range > (100000 * 1))) // 减区
        {
            utmZone -= 1;
            // 投影坐标
            OGRSpatialReference spatialReference;
            spatialReference.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
            spatialReference.SetUTM(utmZone, true);

            // 地理坐标
            OGRSpatialReference *pLonLat = spatialReference.CloneGeogCS();
            mLonLat2XY = OGRCreateCoordinateTransformation(&spatialReference, pLonLat);
        }

        // 记录最后一行 X
        lastLongitude = longitude;

        double latitude = list.at(2).toDouble();
        if(!mLonLat2XY->Transform(1, &longitude, &latitude))
        {
            emit AppSignal::getInstance()->sgl_occur_system_error(QString("数据坐标 (%1, %2) 无法转换，流程结束").arg(QString::number(longitude), QString::number(latitude)));
            return;
        }
        listData.append({ dateTimeString.toStdString(), (uint32_t)datetime.toSecsSinceEpoch(), longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);

    fileDescripter.close();
    delete pLonLat;
}

void CustomFileParser::parseVersion2(std::ifstream &fileDescripter)
{
    QList<PointDetail> listData;
    string line;
    while (getline(fileDescripter, line))
    {
        QString value = QString::fromStdString(line).trimmed().remove('\n');

        if (!value.startsWith("\"$GPRMC")) continue;
        if (value.length() != 90) continue;
        value = value.remove("\"").remove("$");

        QStringList list = value.split(',', Qt::SkipEmptyParts);

        if (list.length() < 14) continue;
        list = list.mid(0, 14);
        if(list.at(12).size() != 4) continue;

        QByteArray input = QByteArray::fromStdString(list.mid(0, 12).join(',').toStdString()) + QByteArray::fromStdString(QString(",%1").arg(list.at(12).at(0)).toStdString());
        QByteArray sum = QByteArray::fromStdString(list.at(12).right(2).toStdString());

        // check sum
        uint32_t len = input.size();
        uint32_t result = 0;
        for (uint32_t i = 0; i < len; i++)
        {
            result = result ^ input.at(i);
        }
        if (result != sum.toUInt(nullptr, 16)) return;

        QString dateStr = list.at(9);
        QDate date = QDate::fromString(dateStr, "ddMMyy");
        date = date.addYears(100);

        QString timeStr = list.at(1);
        if(timeStr.size() != 6) return;
        QTime time = QTime::fromString(timeStr, "hhmmss");
        time = time.addSecs(8 * 60 * 60);

        // 时间戳
        uint32_t timeStamp = QDateTime(date, time).toSecsSinceEpoch();

        QString dateTimeString = QDateTime(date, time).toString("yyyy-MM-dd-hh:mm:ss");

        // 经度
        QString lon_flag = list.at(6);
        QString lon = list.at(5);

        double longitude = (lon_flag == "E") ? (lon.midRef(0, 3).toInt() + lon.midRef(3).toDouble() / 60) : ((lon.midRef(0, 4).toInt() - lon.midRef(4).toDouble() / 60));

        // 纬度
        QString lat_flag = list.at(4);
        QString lat = list.at(3);

        double latitude = (lat_flag == "N") ? (lat.midRef(0, 2).toInt() + lat.midRef(2).toDouble() / 60) : ((lat.midRef(0, 3).toInt() - lat.midRef(3).toDouble() / 60));

        listData.append({ dateTimeString.toStdString(), timeStamp, longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);

    fileDescripter.close();
}

void CustomFileParser::parseVersion3(std::ifstream &fileDescripter)
{
    QList<PointDetail> listData;
    string line;
    while (getline(fileDescripter, line))
    {
        QString value = QString::fromStdString(line).trimmed().remove('\n');

        if (!value.startsWith("\"$GPGGA")) continue;
        if (value.length() != 87) continue;
        value = value.remove("\"").remove("$");

        QStringList list = value.split(',', Qt::SkipEmptyParts);

        if (list.length() < 15) continue;
        list = list.mid(0, 15);
        if(list.at(13).size() != 3) continue;

        QByteArray input = QByteArray::fromStdString(list.mid(0, 13).join(',').toStdString());
        QByteArray sum = QByteArray::fromStdString(list.at(13).right(2).toStdString());

        // check sum
        uint32_t len = input.size();
        uint32_t result = 0;
        for (uint32_t i = 0; i < len; i++)
        {
            result = result ^ input.at(i);
        }
        if (result != sum.toUInt(nullptr, 16)) continue;

        QString dateTimeString = list.at(14);

        // 时间戳
        uint64_t timeStamp = QDateTime::fromString(dateTimeString, "yyyy-MM-dd hh:mm:ss").toSecsSinceEpoch();
        dateTimeString = QDateTime::fromString(dateTimeString, "yyyy-MM-dd hh:mm:ss").toString("yyyy-MM-dd-hh:mm:ss");

        // 经度
        QString lon_flag = list.at(5);
        QString lon = list.at(4);

        double longitude = (lon_flag == "E") ? (lon.midRef(0, 3).toInt() + lon.midRef(3).toDouble() / 60) : ((lon.midRef(0, 4).toInt() - lon.midRef(4).toDouble() / 60));

        // 纬度
        QString lat_flag = list.at(3);
        QString lat = list.at(2);

        double latitude = (lat_flag == "N") ? (lat.midRef(0, 2).toInt() + lat.midRef(2).toDouble() / 60) : ((lat.midRef(0, 3).toInt() - lat.midRef(3).toDouble() / 60));

        listData.append({ dateTimeString.toStdString(), (uint32_t)timeStamp, longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);

    fileDescripter.close();
}

void CustomFileParser::parseVersion4(std::ifstream &fileDescripter)
{
    QList<PointDetail> listData;
    string line;
    while (getline(fileDescripter, line))
    {
        QString value = QString::fromStdString(line).trimmed().remove('\n');

        if (!value.startsWith("$PTSAG")) continue;
        if (value.length() != 90) continue;
        value = value.remove("$");

        QStringList list = value.split(',', Qt::SkipEmptyParts);

        if (list.length() < 15) continue;
        list = list.mid(0, 15);
        if(list.at(14).size() != 10) continue;

        QByteArray input = QByteArray::fromStdString(list.mid(0, 14).join(',').toStdString()) + QByteArray::fromStdString(QString(",%1").arg(list.at(14).left(7)).toStdString());
        QByteArray sum = QByteArray::fromStdString(list.at(14).right(2).toStdString());

        // check sum
        uint32_t len = input.size();
        uint32_t result = 0;
        for (uint32_t i = 0; i < len; i++)
        {
            result = result ^ input.at(i);
        }

        if (result != sum.toUInt(nullptr, 16)) continue;

        bool flag = list.at(6).toUInt();
        if (!flag) continue;

        QDate date = QDate(list.at(5).toUInt(), list.at(4).toUInt(), list.at(3).toUInt());

        QString timeStr = list.at(2);
        if(timeStr.size() < 6) continue;
        QTime time = QTime::fromString(timeStr, "hhmmss.zzz");
        time = time.addSecs(8 * 60 * 60);

        // 时间戳
        uint64_t timeStamp = QDateTime(date, time).toSecsSinceEpoch();

        QString dateTimeString = QDateTime(date, time).toString("yyyy-MM-dd-hh:mm:ss");

        // 经度
        QString lon_flag = list.at(10);
        QString lon = list.at(9);

        double longitude = (lon_flag == "E") ? (lon.midRef(0, 3).toInt() + lon.midRef(3).toDouble() / 60) : ((lon.midRef(0, 4).toInt() - lon.midRef(4).toDouble() / 60));

        // 纬度
        QString lat_flag = list.at(8);
        QString lat = list.at(7);

        double latitude = (lat_flag == "N") ? (lat.midRef(0, 2).toInt() + lat.midRef(2).toDouble() / 60) : ((lat.midRef(0, 3).toInt() - lat.midRef(3).toDouble() / 60));

        listData.append({ dateTimeString.toStdString(), (uint32_t)timeStamp, longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);

    fileDescripter.close();
}

void CustomFileParser::parseVersion5(std::ifstream &fileDescripter)
{
    QList<PointDetail> listData;
    string line;
    while (getline(fileDescripter, line))
    {
        QString value = QString::fromStdString(line).trimmed().remove('\n');
        QStringList list = value.split(',', Qt::SkipEmptyParts);

        if (list.length() < 9) continue;

        // 时间戳
        QDateTime dateTime = QDateTime::fromString(list.at(0), "yyyy/M/dd hh:mm:ss.zzz");
        QString dateTimeString = dateTime.toString("yyyy-MM-dd-hh:mm:ss");
        uint64_t timeStamp = dateTime.toSecsSinceEpoch();

        // 经度
        QString lon = list.at(2);
        lon = lon.remove("E").remove("W");
        auto lonList = lon.split(";");
        if (lonList.size() != 3) continue;
        double longitude = lonList.at(0).trimmed().toInt() + (lonList.at(1).trimmed().toDouble() / 60) + (lonList.at(2).trimmed().toDouble() / 3600);

        // 纬度
        QString lat = list.at(1);
        lat = lat.remove("N").remove("S");
        auto latList = lat.split(";");
        if (latList.size() != 3) continue;
        double latitude = latList.at(0).trimmed().toInt() + (latList.at(1).trimmed().toDouble() / 60) + (latList.at(2).trimmed().toDouble() / 3600);

        listData.append({ dateTimeString.toStdString(), (uint32_t)timeStamp, longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);

    fileDescripter.close();
}

void CustomFileParser::parseVersion6(const QString &path)
{
    QXlsx::Document xlsxDocument(path);
    if (!xlsxDocument.isLoadPackage()) return;

    QXlsx::CellRange range = xlsxDocument.dimension();

    if (range.columnCount() < 10)
    {
        emit AppSignal::getInstance()->sgl_occur_system_error("表格文件格式异常");
        return;
    }

    QList<PointDetail> listData;
    int rowCount = range.rowCount();
    for (int i = 3; i <= rowCount; i++)
    {
        QXlsx::Cell cellDateTime = xlsxDocument.cellAt(i, 3);
        QString dateTimeString = cellDateTime.value().toString();
        uint32_t timeStamp = QDateTime::fromString(dateTimeString, "yyyy-MM-dd hh:mm:ss").toSecsSinceEpoch();

        QXlsx::Cell cellPosition = xlsxDocument.cellAt(i, 5);
        QString valuePosition = cellPosition.value().toString();

        auto list = valuePosition.split("_x000D_\n", Qt::SkipEmptyParts);

        if (list.size() != 2) continue;

        QString latValue = list.at(0);
        latValue.remove("'").remove("S").remove("N");

        auto latList = latValue.split("\u00ba", Qt::SkipEmptyParts);
        if (latList.size() != 2) continue;

        double latitude = latList.at(0).toInt() + latList.at(1).toDouble() / 60;

        QString lonValue = list.at(1);
        lonValue.remove("'").remove("E").remove("W");

        auto lonList = lonValue.split("\u00ba", Qt::SkipEmptyParts);
        if (lonList.size() != 2) continue;

        double longitude = lonList.at(0).toInt() + lonList.at(1).toDouble() / 60;

        listData.append({ dateTimeString.toStdString(), timeStamp, longitude, latitude, true });
    }

    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);
}

void CustomFileParser::parseVersion7(const QString &path)
{
    ExcelFormat::BasicExcel xls(path.toStdString().data());
    if (xls.GetTotalWorkSheets() == 0)
    {
        emit AppSignal::getInstance()->sgl_occur_system_error("系统异常，请联系管理员");
        return;
    }
    ExcelFormat::BasicExcelWorksheet* sheet = xls.GetWorksheet(0);

    QList<PointDetail> listData;
    int rows = sheet->GetTotalRows();
    for (int i = 0; i < rows; i++)
    {
        QString dateTimeString = sheet->Cell(i, 2)->GetString();
        uint32_t timeStamp = QDateTime::fromString(dateTimeString, "yyyy-MM-dd hh:mm:ss").toSecsSinceEpoch();
        QString valuePosition = sheet->Cell(i, 4)->GetString();

        auto list = valuePosition.split("\r\n", Qt::SkipEmptyParts);

        if (list.size() != 2) continue;

        QString latValue = list.at(0);
        latValue.remove("'").remove("S").remove("N");

        auto latList = latValue.split("\ufffd", Qt::SkipEmptyParts);
        if (latList.size() != 2) continue;

        double latitude = latList.at(0).toInt() + latList.at(1).toDouble() / 60;

        QString lonValue = list.at(1);
        lonValue.remove("'").remove("E").remove("W");

        auto lonList = lonValue.split("\ufffd", Qt::SkipEmptyParts);
        if (lonList.size() != 2) continue;

        double longitude = lonList.at(0).toInt() + lonList.at(1).toDouble() / 60;

        listData.append({ dateTimeString.toStdString(), timeStamp, longitude, latitude, true });
    }
    emit AppSignal::getInstance()->sgl_parse_file_result(mCurrentPath, listData);
}

void CustomFileParser::threadExportPointData(const QString &fileName, const QList<PointDetail> &detail)
{
    ofstream fileDescripter(fileName.toLocal8Bit());
    if (!fileDescripter.is_open())
    {
        // 发送系统消息
        emit AppSignal::getInstance()->sgl_occur_system_error("创建文件失败");
        return;
    }

    std::string content = "";
    for (auto value : detail)
    {
        if (!value.valid()) continue;
        QString longitude = QString::number(value.x(), 'f', 6);
        QString latitude = QString::number(value.y(), 'f', 6);
        QString datetime = value.timeStr().data();

        QString line = QString("%1 %2 %3\n").arg(longitude, latitude, datetime);
        content += line.toStdString();
    }

    fileDescripter.write(content.data(), content.length());
    fileDescripter.flush();
    fileDescripter.close();

    emit AppSignal::getInstance()->sgl_occur_system_success("导出完成");
}

bool CustomFileParser::isDefaultVersion(const QString &line)
{
    auto list = line.split(" ", Qt::SkipEmptyParts);
    if (list.size() != 3) return false;

    QDateTime datetime = QDateTime::fromString(list.at(2), "yyyy-MM-dd-hh:mm:ss.zzz");
    return datetime.isValid();
}
